如何在 react / textarea 中替换 'selected text' => 'decorated text'?我无法获得 'selected text' 的确切位置(索引)

how to replace 'selected text' => 'decorated text' in react / textarea? i can't get exact location(index) of 'selected text'

我正在尝试用 React 构建一些文本编辑器

我的母语不是英语,很抱歉回答下面的问题


我想做的是下面这样

(it's 'notion' page gif)

我被第一个卡住了。

我可以得到整个文本和选定的文本

但我无法在 wholeText

中获得 selectedText 的 'exact location'

这是我的代码(反应,样式组件)

import { useState, useEffect } from 'react';
import styled from 'styled-components';
import autosize from 'autosize';

export default function TextBox({ id, index, content, handleContentInput }) {
  const [currentContent, setCurrentContent] = useState(content);
  const [areaHeight, setAreaHeight] = useState(25);

  useEffect(() => {
    autosize(document.querySelector(`.TextBoxWrap_${id}`));
  }, [currentContent]);

  return (
    <TextBoxContainer
      className={`TextBoxContainer_${id}`}
      areaHeight={areaHeight}
      onClick={() => {
        document.querySelector(`.TextBoxContainer_${id}`).focus();
      }}
    >
      <TextBoxWrap
        className={`TextBoxWrap_${id}`}
        areaHeight={areaHeight}
        onChange={(event) => {
          setCurrentContent(event.target.value);
        }}
        onBlur={() => handleContentInput(id, index, currentContent)}
        onKeyUp={() => {
          let newHeight = document.querySelector(`.TextBoxWrap_${id}`)
            .clientHeight;
          setAreaHeight(newHeight);
        }}
        onMouseUp={() => {
          let whole = window.getSelection();
          if (!whole) return;

          let range = whole.getRangeAt(0);

          console.log({ whole, range });

          let wholeText = whole.anchorNode.childNodes[0].defaultValue;

          let selectedText = whole.toString();

          console.log({ wholeText, selectedText });

          let start = range.startOffset; // Start position
          let end = range.endOffset; // End position

          console.log({ start, end });
        }}
        value={currentContent}
      ></TextBoxWrap>
    </TextBoxContainer>
  );
}

const TextBoxContainer = styled.div`
  max-width: 890px;
  width: 100%;
  height: ${(props) => `${props.areaHeight}px`};

  border: 1px solid black;
  margin: 3px;
  padding: 2px;
`;

const TextBoxWrap = styled.textarea`
  /* border: 1px solid black; */
  box-sizing: 'border-box';
  border: none;
  outline: none;

  width: 100%;
  min-height: 20px;
  height: 20px;

  /* padding: 2x; */
  box-shadow: none;
  display: block;
  overflow: hidden; // Removes scrollbar
  resize: none;
  font-size: 18px;
  /* line-height: 1.5em; */
  /* font-family: Georgia, 'Malgun Gothic', serif; */
`;

onMouseUp里面,它是这样工作的

wholeText.indexOf(selectedText) 是我的选择,但 indexOf() 只给我 'first' 索引匹配,

所以,即使我想要“aaaaaa'a'aa”,但 indexOf 会给我“0”(=>“'a'aaaaaaaaaa”)


我在想什么,

这意味着,我需要'选择一个人的位置


我该怎么做?请给我建议

谢谢!


post我之前看过post这个问题

我可能对我的问题有一些解决方案,所以 post 我自己回答这个问题


在这个问题(How to get the start and end points of selection in text area?)中,'Tim Down'用getInputSelection函数回答。

getInputSelection 需要 el 作为参数,我认为这是某种 'html element'

所以,根据这个问题(使用 javascript 获取焦点元素的 ID ),我得到了一个提示:document.activeElement

而且,我尝试了 getInputSelection(document.activeElement) 并得到了一个像 { start: (number), end: (number) }

这样的对象